local duf = _G.DeclarativeUnitFrames

function duf.virtual_class_handlers:FontString(state, decl, add)
	add("local frame = parent:CreateFontString(%s, %s, %s)", 
		self:GetValue(state, decl, "name"), self:GetValue(state, decl, "layer", "ARTWORK"), self:GetValue(state, decl, "template", "GameFontNormal"))
	if decl.text then
		self:AddCallback(state, decl, add, "FontString_SetText", function(state, decl, add)
			add("frame:SetText(%s)", self:GetValue(state, decl, "text", "", "FontString_SetText"))
		end)
		add("FontString_SetText()")
	end
end

function duf.virtual_class_handlers:Texture(state, decl, add)
	add("local frame = parent:CreateTexture(%s, %s, %s)", 
		self:GetValue(state, decl, "name"), self:GetValue(state, decl, "layer", "ARTWORK"), self:GetValue(state, decl, "template"))
	if decl.texture then
		self:AddCallback(state, decl, add, "Texture_SetTexture", function(state, decl, add)
			local f = loadstring("return "..self:GetValue(state, decl, "texture", "", "Texture_SetTexture"))
			add("frame:SetTexture(%s)", f())
		end)
		add("Texture_SetTexture()")
	elseif decl.portrait_texture then
		self:AddCallback(state, decl, add, "Texture_SetPortraitTexture", function(state, decl, add)
			local unit = self:GetValue(state, decl, "portrait_texture", "", "Texture_SetPortraitTexture")
			add("SetPortraitTexture(frame, %s)", unit)
		end)
		self:AddEvent(state, decl, "UNIT_PORTRAIT_UPDATE", "Texture_SetPortraitTexture", unit)
		add("Texture_SetPortraitTexture()")
	end
end

function duf.virtual_class_handlers:PlayerAuraContainer(state, decl, add)
	add("local frame = CreateFrame(\"Frame\", %s, parent, %s)", 
		self:GetValue(state, decl, "name"), self:GetValue(state, decl, "template"))
	add("local layout = %s", decl.layout)
	add("frame.auras = {}")
	add("frame.filter = %s", self:GetImmediateValue(state, decl, decl.filter))
	self:AddCallback(state, decl, add, "PlayerAuraContainer_UpdateAuras", function(state, decl, add)
		add("ShowPlayerAuras(frame)")
	end)
	self:AddEvent(state, decl, "PLAYER_AURAS_CHANGED", "PlayerAuraContainer_UpdateAuras")
	add("for id = 1, %d do", decl.max or 40)
	add("\tlocal parent = frame")
	add("\tdo")
	local prev_cb_checkisshown = state.callback_checkisshown
	state.callback_checkisshown = true
	self:FrameGenerator(state, decl.child_template, function (s, ...) add("\t\t"..s, ...) end)
	state.callback_checkisshown = prev_cb_checkisshown
	add("\t\tlayout(parent, frame, id)")
	add("\t\tparent.auras[id] = frame")
	add("\tend")
	add("end")
	add("PlayerAuraContainer_UpdateAuras()")
	self:RegisterUtil(state, "ShowPlayerAuras")
end

function duf.Utils.ShowPlayerAuras(frame)
	local auras = frame.auras
	local filter = frame.filter
	for i = 1, #auras do
		local aura = auras[i]
		local id = GetPlayerBuff(i, filter)
		if id > 0 then
			aura:SetID(id)
			aura:Show()
		else
			aura:Hide()
		end
	end
end

function duf.virtual_class_handlers:UnitBuffContainer(state, decl, add)
	add("local frame = CreateFrame(\"Frame\", %s, parent, %s)", 
		self:GetValue(state, decl, "name"), self:GetValue(state, decl, "template"))
	add("local layout = %s", self:GetImmediateValue(state, decl, decl.layout))
	add("frame.buffs = {}")
	add("frame.filter = %s", self:GetImmediateValue(state, decl, decl.filter))
	self:AddCallback(state, decl, add, "UnitAuraContainer_UpdateAuras", function(state, decl, add)
		add("ShowUnitBuffs(frame)")
	end)
	self:AddEvent(state, decl, "UNIT_AURA", "UnitAuraContainer_UpdateAuras")
	add("for id = 1, %d do", decl.max or 40)
	add("\tlocal parent = frame")
	add("\tdo")
	local prev_cb_checkisshown = state.callback_checkisshown
	state.callback_checkisshown = true
	self:FrameGenerator(state, decl.child_template, function (s, ...) add("\t\t"..s, ...) end)
	state.callback_checkisshown = prev_cb_checkisshown
	add("\t\tlayout(parent, frame, id)")
	add("\t\tparent.buffs[id] = frame")
	add("\tend")
	add("end")
	add("UnitAuraContainer_UpdateAuras()")
	self:RegisterUtil(state, "ShowUnitBuffs")
end

function duf.Utils.ShowUnitBuffs(frame)
	local buffs = frame.buffs
	local unit = frame.unit
	local filter = frame.filter
	for i, aura in ipairs(auras) do
		if UnitBuff(unit, i, filter) then
			aura:Show()
		else
			aura:Hide()
		end
	end
end

function duf.Utils.ShowUnitDebuffs(frame)
	local debuffs = frame.debuffs
	local unit = frame.unit
	local filter = frame.filter
	for i, aura in ipairs(auras) do
		if UnitBuff(unit, i, filter) then
			aura:Show()
		else
			aura:Hide()
		end
	end
end

